//导入路由脚本文件中的属性，对应了是否拥有对应的角色权限，详情可以到对应文件中查看，有备注信息
import {constantRoutes} from '@/router'
//导入获取菜单数据的方法
import {getMenuList} from "@/api/user";
//导入layout组件
import Layout from '@/layout'

/**
 * 使用 meta.role 确定当前用户是否具有权限
 * 判断当前用户是否具有该角色下的菜单信息
 * @param roles
 * @param route
 */
function hasPermission(roles, route) {
  if (route.meta && route.meta.roles) {
    return roles.some(role => route.meta.roles.includes(role))
  } else {
    return true
  }
}

/**
 * 按递归筛选异步路由表
 * 过滤出所拥有的菜单信息
 * @param routes asyncRoutes
 * @param roles
 */
export function filterAsyncRoutes(routes, roles) {
  const res = []
  routes.forEach(route => {
    const tmp = {...route}
    //判断当前用户是否具有该角色下的菜单信息，也就是是否有相应权限
    if (hasPermission(roles, tmp)) {
      //获取组件
      const component = tmp.component;
      //判断该路由使用有组件
      if (route.component) {
        //判断是否根组件
        if (component === 'Layout') {
          tmp.component = Layout;
        } else {
          //获取对应的具体的组件信息
          tmp.component = (resolve) => require([`@/views${component}`], resolve)
        }
      }
      //判断该路由是否有子路由
      if (tmp.children) {
        tmp.children = filterAsyncRoutes(tmp.children, roles)
      }
      res.push(tmp)
    }
  })
  return res
}

const state = {
  routes: [],
  addRoutes: []
}

const mutations = {
  //将路由信息保存到store中(Vuex)
  SET_ROUTES: (state, routes) => {
    state.addRoutes = routes
    state.routes = constantRoutes.concat(routes)
  }
}

const actions = {
  /**
   * 根据用户角色生成路由信息
   * @param commit
   * @param roles
   * @returns {Promise<unknown>}
   */
  generateRoutes({commit}, roles) {
    return new Promise((resolve, reject) => {
      //发送查询菜单数据的请求
      getMenuList().then(res => {
        // console.log(res);
        //存放对应权限的路由信息
        let accessedRoutes;
        //如果状态码为200，则表示成功
        if (res.code === 200) {
          accessedRoutes = filterAsyncRoutes(res.data, roles)
          // accessedRoutes=filterAsyncRoutes(asyncRoutes, roles)
        }
        //将路由信息保存到store中
        commit('SET_ROUTES', accessedRoutes);
        resolve(accessedRoutes)
      }).catch(error => {
        reject(error)
      })
    });
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}
